package com.zemo.base.common.util;


import com.google.common.collect.Maps;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Value;

import java.io.IOException;
import java.net.URI;
import java.util.Map;

/**
 * Created by zemo on 2016-05-23 22:26:13
 */
public class WeiXinAuthUtil {

    @Value("weixin.login.appid")
    public static String APP_ID;
    @Value("wxpay.appsecret")
    public static  String APP_SECRET;
    @Value("weixin.redirectUri")
    public static  String REDIRECT_URI;

    public static final String SCOPE_USERINFO = "snsapi_userinfo";
    public static final String SCOPE_BASE = "snsapi_base";


    /**
     * 获取微信授权地址
     *
     * @param state 自定义参数 会在回调中传回
     * @return
     * @throws IOException
     */
    public static String getAuthUrl(String state, String scope, String redirectUri) throws IOException {
        String url = "";
        try {
            URI uri = new URIBuilder()
                    .setScheme("https")
                    .setHost("open.weixin.qq.com")
                    .setPath("/connect/oauth2/authorize")
                    .setParameter("appid", APP_ID)
                    .setParameter("redirect_uri", redirectUri)
                    .setParameter("response_type", "code")
                    .setParameter("scope", scope)
                    .setParameter("state", state)
                    .setFragment("wechat_redirect")
                    .build();

            url = uri.toString();
        } catch (Exception e) {
        }
        return url;
    }

    public static String getAccessToken() throws IOException {
        CloseableHttpClient httpclient = HttpClients.createDefault();
        try {

            URI uri = new URIBuilder()
                    .setScheme("https")
                    .setHost("api.weixin.qq.com")
                    .setPath("/cgi-bin/token")
                    .setParameter("grant_type", "client_credential")
                    .setParameter("appid", APP_ID)
                    .setParameter("secret", APP_SECRET)
                    .build();


            HttpGet httpget = new HttpGet(uri);
//            System.out.println(httpget.getURI());

//            System.out.println("Executing request " + httpget.getRequestLine());


            String responseBody = httpclient.execute(httpget, handlerResponse());
            Map<String, Object> datas = JsonUtils.toObject(responseBody, Map.class);
            /*for (String s : datas.keySet()) {
                System.out.println(s+" ："+datas.get(s));
            }*/
            return (String) datas.get("access_token");
        } catch (Exception e) {

        } finally {
            httpclient.close();
        }
        return null;
    }

    /**
     * step 2. 通过code换取网页授权access_token
     *
     * @param code
     * @return "access_token":"ACCESS_TOKEN",
     * "expires_in":7200,
     * "refresh_token":"REFRESH_TOKEN",
     * "openid":"OPENID",
     * "scope":"SCOPE",
     * "unionid": "o6_bmasdasdsad6_2sgVt7hMZOPfL"
     * @throws IOException
     */
    public static Map<String, Object> getUserAccessToken(String code, int count) throws IOException {
        Map<String, Object> map = Maps.newHashMap();
        map.put("title", "weixin login");
        CloseableHttpClient httpclient = HttpClients.createDefault();
        try {
            URI uri = new URIBuilder()
                    .setScheme("https")
                    .setHost("api.weixin.qq.com")
                    .setPath("/sns/oauth2/access_token")
                    .setParameter("code", code)
                    .setParameter("grant_type", "authorization_code")
                    .setParameter("appid", APP_ID)
                    .setParameter("secret", APP_SECRET)
                    .build();
            HttpGet httpget = new HttpGet(uri);

            System.out.println(httpget.getURI());
            System.out.println("Executing request " + httpget.getRequestLine());

            String responseBody = httpclient.execute(httpget, handlerResponse());
            map = JsonUtils.toObject(responseBody, Map.class);

            map.put("status", true);
        } catch (Exception e) {
            //重试3次
            if (count < 3) {
                getUserAccessToken(code, count++);
            } else {
                map.put("status", false);
                e.printStackTrace();
            }
        } finally {
            httpclient.close();
        }
        return map;
    }

    /**
     * 获取用户信息
     *
     * @param openId
     * @param accessToken
     * @return
     * @throws IOException
     */
    public static Map<String, Object> getUserInfo(String openId, String accessToken) throws IOException {
        Map<String, Object> map = Maps.newHashMap();
        CloseableHttpClient httpclient = HttpClients.createDefault();
        try {
            URI uri = new URIBuilder()
                    .setScheme("https")
                    .setHost("api.weixin.qq.com")
                    .setPath("/sns/userinfo")
                    .setParameter("access_token", accessToken)
                    .setParameter("openid", openId)
                    .setParameter("lang", "zh_CN")
                    .build();
            HttpGet httpget = new HttpGet(uri);

            String responseBody = httpclient.execute(httpget, handlerResponse());
            map = JsonUtils.toObject(responseBody, Map.class);
            map.put("status", true);
        } catch (Exception e) {
            map.put("status", false);
            e.printStackTrace();
        } finally {
            httpclient.close();
        }
        return map;
    }

    public static Map<String, Object> getApiTicket(String type) throws IOException {
        CloseableHttpClient httpclient = HttpClients.createDefault();
        Map<String, Object> map = Maps.newHashMap();
        try {
            URI uri = new URIBuilder()
                    .setScheme("https")
                    .setHost("api.weixin.qq.com")
                    .setPath("/cgi-bin/ticket/getticket")
                    .setParameter("access_token", getAccessToken())
                    .setParameter("type", type)
                    .build();
            HttpGet httpget = new HttpGet(uri);

            String responseBody = httpclient.execute(httpget, handlerResponse());
            map = JsonUtils.toObject(responseBody, Map.class);
            map.put("status", true);
        } catch (Exception e) {
            map.put("status", false);
            e.printStackTrace();
        } finally {
            httpclient.close();
        }
        return map;
    }

    // Create a custom response handler
    private static ResponseHandler<String> handlerResponse() {
        ResponseHandler<String> responseHandler = new ResponseHandler<String>() {

            public String handleResponse(
                    final HttpResponse response) throws ClientProtocolException, IOException {
                int status = response.getStatusLine().getStatusCode();
                if (status >= 200 && status < 300) {
                    HttpEntity entity = response.getEntity();
                    return entity != null ? EntityUtils.toString(entity, "UTF-8") : null;
                } else {
                    throw new ClientProtocolException("Unexpected response status: " + status);
                }
            }

        };
        return responseHandler;
    }

    public static void main(String[] args) throws IOException {
//        String authUrl = getAuthUrl(REDIRECT_URI);
//        System.out.println(authUrl);
//        HttpGet httpget = new HttpGet(authUrl);
        //step 1 获取code
        //step 2. 通过code换取网页授权access_token,openid
        //step 3. 通过access_token+openid获取用户信息
//        System.out.println(getAuthUrl("/acativity"));
        /*Map<String, Object> map = getUserAccessToken("041a29be6dcfc02a2b3209609babf15k",0);
        for (String s : map.keySet()) {
            System.out.println(s + " : " + map.get(s));
        }
        */

        System.out.println("-----ticket----------");
        Map<String, Object> ticketMap = getApiTicket("jsapi");
        for (String s : ticketMap.keySet()) {
            System.out.println(s + ":" + ticketMap.get(s));
        }

        System.out.println(getAccessToken());
    }
}
